package com.quanz.ckgl.services.db;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.crank.crud.CriteriaUtils;
import org.crank.crud.criteria.Criterion;
import org.crank.crud.criteria.OrderBy;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.quanz.ckgl.services.Rack;
import com.quanz.ckgl.services.RackService;
import com.quanz.ckgl.services.dao.RackDao;
import com.quanz.ckgl.services.entity.RackEntity;

/**
 * 基于数据库的{@link RackService}实现
 * @author James Quan
 * @version 2015年10月9日 下午9:41:49
 */
@Component
public class DbRackService implements RackService {
	private RackDao rackDao;

	public RackDao getRackDao() {
		return rackDao;
	}

	@Resource
	public void setRackDao(RackDao rackDao) {
		this.rackDao = rackDao;
	}
	
	@Override
	@Transactional(readOnly = true)
	public Rack findRackById(String id) {
		RackEntity entity = rackDao.findOne(id);
		return wrap(entity);
	}

	@Override
	@Transactional(readOnly = true)
	public Rack[] findRack(OrderBy[] orderBy, int startPosition, int maxResults, Criterion... criteria) {
		Specification<RackEntity> spec = CriteriaUtils.getSpecification(RackEntity.class, criteria);
		Sort sort = CriteriaUtils.getSort(orderBy);
		List<RackEntity> entities = rackDao.findList(spec, startPosition, maxResults, sort);
		List<Rack> racks = new ArrayList<Rack>(entities.size());
		for (RackEntity entity : entities) {
			Rack rack = wrap(entity);
			racks.add(rack);
		}
		return racks.toArray(new Rack[racks.size()]);
	}

	@Override
	@Transactional(readOnly = true)
	public int findRackCount(Criterion... criteria) {
		Specification<RackEntity> spec = CriteriaUtils.getSpecification(RackEntity.class, criteria);
		long c = rackDao.count(spec);
		return (int)c;
	}

	@Override
	@Transactional
	public Rack createRack(Rack rack) {
		if (findRackById(rack.getId()) != null) {
			throw new DuplicateKeyException("rack " + rack.getId() + " already existed!");
		}
		RackEntity entity = new RackEntity();
		entity.setId(rack.getId());
		entity.setIndex(rack.getIndex());
		entity.setLayers(rack.getLayers());
		entity.setCols(rack.getCols());
		entity.setColor(rack.getColor());
		entity.setNote(rack.getNote());
		rackDao.persist(entity);
		return wrap(entity);
	}

	@Override
	@Transactional
	public void updateRack(Rack rack) {
		RackEntity entity = rackDao.findOne(rack.getId());
		if (entity == null) {
			throw new IllegalArgumentException("rack " + rack.getId() + " not found!");
		}
		entity.setIndex(rack.getIndex());
		entity.setLayers(rack.getLayers());
		entity.setCols(rack.getCols());
		entity.setColor(rack.getColor());
		entity.setNote(rack.getNote());
		entity = rackDao.merge(entity);
	}

	@Override
	@Transactional
	public void removeRack(Rack rack) {
		RackEntity entity = rackDao.findOne(rack.getId());
		if (entity == null) {
			return;
		}
		rackDao.delete(entity);
	}
	
	protected Rack wrap(RackEntity entity) {
		if(entity == null) {
			return null;
		}
		Rack rack = new Rack();
		rack.setId(entity.getId());
		rack.setIndex(entity.getIndex());
		rack.setLayers(entity.getLayers());
		rack.setCols(entity.getCols());
		rack.setColor(entity.getColor());
		rack.setNote(entity.getNote());
		return rack;
	}
}
